#ifndef _POPULATION_H_
#define _POPULATION_H_

#include "logger.h"

#include <vector>
#include <deque>

class Individual;
class Prision;


class Population
{
  public:
    Population(int p_size, float p_crossover_rate, float p_mutation_rate);
    virtual ~Population();
    // Run the algorithm for a defined number of generations.
    void evolve(int p_generations);


  private:
    // Population params.
    int m_size;
    // Individual params.
    float m_crossover_rate;
    float m_mutation_rate;
    // The individuals.
    std::vector<Individual *> m_individuals;
    std::vector<Individual *> m_intermediate_individuals;
    // The prision they play in.
    Prision *m_prision;
    // Average fitness for the population at any given generation.
    std::deque<unsigned int> m_average_fitness;
    // The number of generations that have been processed.
    unsigned int m_current_generation;
    // Helper to log stats to files.
    Logger m_logger;
    

  private:
    // Create the initial population and init other population stuff.
    void init();
    // Algorithm steps.
    void selectIndividuals();
    void crossIndividuals();
    void mutateIndividuals();
    void evaluateIndividuals(); // Get each individual's fitness.
    // Selection mechanism.
    void rouletteSelection();
    // Operations over the population.
    void clearPopulation();
    void clearIntermediatePopulation();
    // Get statistics for the population at its current state.
    void openLogs();
    void closeLogs();
    void collectStats(unsigned int p_generation);
    // Examine the average fitness deque for a specific fitness,
    // ... or calculate it.
    unsigned int getAverageFitness();
    Individual *getFitestIndividual();
    Individual *getWorstIndividual();
};


#endif /* _POPULATION_H_ */
